import pygame
from pygame import *

import gui

import storyxml
import crumbs
import sys
import re

out = gui.GUI()

loc = None
parser = crumbs.CrumbParser()

def doItem(node):
	
	if hasattr(node, "parsed") == False:
		point = node._parent
		if node._parent._name != "location":
			point = crumbs.parsePath(node, "$location")
			if point == 0:
				point = node._parent
		print "Item", node.id, "added to", point.id
		
		if hasattr(point, "items") == False:
			point.items = []
			
		point.items.append(node)
		node._parent = point
		node.parsed = "yes"
		
	if node.parsed=="done":
		return (0, [])
	else:
		said = crumbs.parseText(node._parent, node.text)
		out.addLine(said)
	return (1, [])

def doJump(node):
	global loc
	global parser
	if hasattr(node, "jumped") and node.jumped == True:  #we've already jumped, so die. slowly. painfully.
		return (1, [])
	if hasattr(node, "text"):
		out.addLine(crumbs.parseText(node, node.text))
		
	point = crumbs.parsePath(node, node.parse)
	if point != 0:
		loc = point
	else:
		print "Can't find jump location", node.parse
		return (0, [])
	
	out.addLine("Press any key to travel to " + crumbs.parseText(loc, loc.text))
	sel = 0
	while sel == 0:
		
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			if event.type == KEYDOWN:
				if event.key == K_ESCAPE:
					sys.exit()
				elif (event.key == K_UP or event.key == K_w):
					out.up()
				elif (event.key == K_DOWN or event.key == K_s):
					out.down()
				elif event.key == K_HOME:
					out.home()
				elif event.key == K_END or event.key == K_x:
					out.end()
				else:
					sel = 1
					
		pygame.display.update()
	
	out.popLines(1)
	out.addLine("-- Travelled to: " + crumbs.parseText(loc, loc.text))
	
	node.jumped = True
		
	parser.parseCrumb(loc, True)
	if len(loc._children) == 0:
		out.addLine("There seems to be nothing here.")
		
	node.jumped = False
	return (3, [])

def doJumpOnce(node):
	global loc
	global parser
	if hasattr(node, "jumped") and node.jumped == True:  #we've already jumped, so die. slowly. painfully.
		return (0, [])
	if hasattr(node, "text"):
		out.addLine(crumbs.parseText(node, node.text))
		
	point = crumbs.parsePath(node, node.parse)
	if point != 0:
		loc = point
	else:
		print "Can't find jump location", node.parse
		return (0, [])
	
	out.addLine("Press any key to travel to " + crumbs.parseText(loc, loc.text))
	sel = 0
	while sel == 0:
		
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			if event.type == KEYDOWN:
				if event.key == K_ESCAPE:
					sys.exit()
				elif (event.key == K_UP or event.key == K_w):
					out.up()
				elif (event.key == K_DOWN or event.key == K_s):
					out.down()
				elif event.key == K_HOME:
					out.home()
				elif event.key == K_END or event.key == K_x:
					out.end()
				else:
					sel = 1
					
		pygame.display.update()
		
	out.popLines(1)
	out.addLine("-- Travelled to: " + crumbs.parseText(loc, loc.text))
	
	node.jumped = True
		
	parser.parseCrumb(loc, True)
	if len(loc._children) == 0:
		out.addLine("There seems to be nothing here.")
		
	node.jumped = False
	return (2, [])

def doEnd(node):
	if hasattr(node, "text"):
		out.addLine(crumbs.parseText(node, node.text))
	out.addLine("The game has now ended. You may continue to scroll through the log, or press ESC to exit.")
	sel = 0
	while sel == 0:
		
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			if event.type == KEYDOWN:
				if event.key == K_ESCAPE:
					sys.exit()
				elif (event.key == K_UP or event.key == K_w):
					out.up()
				elif (event.key == K_DOWN or event.key == K_s):
					out.down()
				elif event.key == K_HOME:
					out.home()
				elif event.key == K_END or event.key == K_x:
					out.end()
				else:
					print "WROOONGGGG"
					sel = 0
			
		pygame.display.update()

def doSelect(node):
	#parse any neccesary nodes
	if hasattr(node, "parse"):
		regex = re.compile(node.parse)
		
		i = 0
		
		while(i < len(node._children)):
			child = node._children[i]
			#print i, child
			if regex.match(child._name) is not None:
				#print "regex matched"
				result = self.parseCrumb(child)
				if result[0] == 0:
					node._children.pop(i)
					i -= 1				#Because it is incremented later, but we don't want it to be. Simplest solution.
					
				for child in result[1]:
					node._children.insert(i, child)
					
				#this should not support jumping! Don't do it!
					
			i += 1
				
	out.addLine(crumbs.parseText(node, node.text))
	
	i = 1
	for choice in node._children:
		out.addLine(str(i) + ": " + crumbs.parseText(node, choice.text))
		i += 1
		
	sel = 0
	while sel == 0:
		
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			if event.type == KEYDOWN:
				if event.key == K_ESCAPE:
					sys.exit()
				elif (event.key == K_UP or event.key == K_w):
					out.up()
				elif (event.key == K_DOWN or event.key == K_s):
					out.down()
				elif event.key == K_HOME:
					out.home()
				elif event.key == K_END or event.key == K_x:
					out.end()
				else:
					try:
						sel = int(event.unicode)
					except Exception, reason:
						sel = 0
					if sel < 1 or sel > len(node._children):
						print "WROOONGGGG"
						sel = 0
			
		pygame.display.update()
		
	#remove unused lines.
	out.popLines(len(node._children))
	out.addLine(crumbs.parseText(node._children[sel - 1], node._children[sel - 1].text))
	
	node._children[sel - 1]._children.reverse()
	
	return (0, node._children[sel - 1]._children)

def doStaticSelect(node):
	global parser

	#parse any neccesary nodes
	if hasattr(node, "parse"):
		regex = re.compile(node.parse)
		
		i = 0
		
		while(i < len(node._children)):
			child = node._children[i]
			#print i, child
			if regex.match(child._name) is not None:
				#print "regex matched"
				result = parser.parseCrumb(child)
				if result[0] == 0:
					node._children.pop(i)
					i -= 1				#Because it is incremented later, but we don't want it to be. Simplest solution.
					
				for child in result[1]:
					node._children.insert(i, child)
					
				#this should not support jumping! Don't do it!
					
			i += 1
	
	out.addLine(crumbs.parseText(node, node.text))
	
	i = 1
	for choice in node._children:
		out.addLine(str(i) + ": " + crumbs.parseText(node, choice.text))
		i += 1
		
	sel = 0
	while sel == 0:
		
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			if event.type == KEYDOWN:
				if event.key == K_ESCAPE:
					sys.exit()
				elif (event.key == K_UP or event.key == K_w):
					out.up()
				elif (event.key == K_DOWN or event.key == K_s):
					out.down()
				elif event.key == K_HOME:
					out.home()
				elif event.key == K_END or event.key == K_x:
					out.end()
				else:
					try:
						sel = int(event.unicode)
					except Exception, reason:
						sel = 0
					if sel < 1 or sel > len(node._children):
						print "WROOONGGGG"
						sel = 0
			
		pygame.display.update()
		
	#remove unused lines.
	out.popLines(len(node._children))
	out.addLine(crumbs.parseText(node._children[sel - 1], node._children[sel - 1].text))
	
	choice = node._children[sel - 1]._children
	
	ret = 1
	if len(choice) > 0:
		i = 0
		while(i < len(choice)):
			result = parser.parseCrumb(choice[i])
			if result[0] == 0 or result[0] == 2:
				choice.pop(i)
				i += 1
			else:
				i += 1
				
			for child in result[1]:
				choice.insert(i, child)
				i -= 1
				
			if result[0] > 1:
				ret = 3
				break
			
	return (ret, [])
	
def doSay(node):
	said = crumbs.parseText(node._parent, node.text)
	print "#####", said
	out.addLine(said)
	return (1, [])

def doSayOnce(node):
	said = crumbs.parseText(node._parent, node.text)
	out.addLine(said)
	return (0, [])
	
def doImage(node):
	#do an image
	out.img(node.file)
	return (1, [])

def doChar(node):
	#do an image
	if hasattr(node, "file"):
		out.img2(node.file)
	else:
		out.img2(None)
	return (1, [])

def doBottom(node):
	#do an image
	out.bottom(node.file)
	return (1, [])

#so staticifs can work in staticselect
def doNothing(node):
	return (1, [])

def main():
	global loc
	global parser
	story = storyxml.getXML("samplenodes.xml")
	node = storyxml.parseXML(story.documentElement)[0]
	parser.registerFunc("select", doSelect)
	parser.registerFunc("staticselect", doStaticSelect)
	parser.registerFunc("choice", doNothing)
	parser.registerFunc("say", doSay)
	parser.registerFunc("sayonce", doSayOnce)
	parser.registerFunc("img", doImage)
	parser.registerFunc("bottom", doBottom)
	parser.registerFunc("char", doChar)
	parser.registerFunc("end", doEnd)
	parser.registerFunc("jump", doJump)
	parser.registerFunc("jumponce", doJumpOnce)
	parser.registerFunc("item", doItem)
	node.locations = []
	parser.parseCrumb(node)
	#print str(node)
	
	loc=node
	
	while out.die == 0:
		#print node
		
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			if event.type == KEYDOWN:
				if event.key == K_ESCAPE:
					sys.exit()
				if event.key == K_UP:
					out.up()
				if event.key == K_DOWN:
					out.down()
					
		out.addLine("You may head to:")
		
		i = 1
		locs = 0
		up = 0
		items = 0
		if hasattr(loc, "locations") == False:
			loc.locations = [] #in case we jumped into somewhere, make sure we have locations!!

		for choice in loc.locations:
			out.addLine(str(i) + ": " + crumbs.parseText(choice, choice.text))
			i += 1
			locs += 1
			
		if loc._parent is not None:
			out.addLine(str(i) + ": (Back) " + crumbs.parseText(loc._parent, loc._parent.text))
			up = i
			i += 1
		
		if hasattr(loc, "items") and len(loc.items) > 0:
			out.addLine(str(i) + ": Pick up an item")
			items = i
			i += 1

		
		sel = 0
		while sel == 0:
			
			for event in pygame.event.get():
				if event.type == QUIT:
					sys.exit()
				if event.type == KEYDOWN:
					if event.key == K_ESCAPE:
						sys.exit()
					elif (event.key == K_UP or event.key == K_w):
						out.up()
					elif (event.key == K_DOWN or event.key == K_s):
						out.down()
					elif event.key == K_HOME:
						out.home()
					elif event.key == K_END or event.key == K_x:
						out.end()
					else:
						try:
							sel = int(event.unicode)
						except Exception, reason:
							sel = 0
						if sel < 1 or sel >= i:
							print "WROOONGGGG"
							sel = 0
							
			pygame.display.update()
			
		out.fg = None
			
		#remove unused lines.
		out.popLines(len(loc.locations) + 1)
		
		if loc._parent is not None:
			out.popLines(1)
			
		if hasattr(loc, "items") and len(loc.items) > 0:
			out.popLines(1)
			
		moved = 0
		if sel <= locs:
			loc = loc.locations[sel - 1]
			moved = 1
		else:
			if sel == up:
				loc = loc._parent
				moved = 1
			elif sel == items:
				done = 0
				while done == 0:
					if len(loc.items) == 0:
						out.addLine("There is nothing left.")
						break
					i = 1
					
					out.addLine("You see:")
					
					for choice in loc.items:
						out.addLine(str(i) + ": " + crumbs.parseText(choice, choice.name))
						i += 1
						
					out.addLine(str(i) + ": I'm done.")
					i += 1
					
					pygame.display.update()
			
					sel = 0
					while sel == 0:
						
						for event in pygame.event.get():
							if event.type == QUIT:
								sys.exit()
							if event.type == KEYDOWN:
								if event.key == K_ESCAPE:
									sys.exit()
								elif (event.key == K_UP or event.key == K_w):
									out.up()
								elif (event.key == K_DOWN or event.key == K_s):
									out.down()
								elif event.key == K_HOME:
									out.home()
								elif event.key == K_END or event.key == K_x:
									out.end()
								else:
									try:
										sel = int(event.unicode)
									except Exception, reason:
										sel = 0
									if sel < 1 or sel >= i:
										print "WROOONGGGG"
										sel = 0
						pygame.display.update()
										
					pygame.display.update()
					
					out.popLines(i)
										
					if sel == i - 1:
						done = 1
					else:
						item = loc.items[sel - 1]
						item.parsed="done"
						inventory = crumbs.parsePath(node, "$root:inventory")
						if inventory == 0:
							print "MASSIVE ERROR: Root node has no child called inventory. ITEMS WILL NOT WORK."
							return
						newitem = storyxml.XMLNode(item.id)
						newitem._parent = inventory
						inventory._children.append(newitem)
						loc.items.pop(sel - 1)
						out.addLine("++ Took the " + item.name + ".")
					
									
			pygame.display.update()
			
		if moved == 1:
			out.addLine("-- Travelled to: " + crumbs.parseText(loc, loc.text))
				
		parser.parseCrumb(loc, True)
		if len(loc._children) == 0:
			out.addLine("There seems to be nothing here.")
				
		pygame.display.update()


if __name__ == '__main__': main()